// Optional view for Mission eventing
// Copyright 2006 (C) Ralph Thomas

#include <view/optional.h>
#include <toolkit/application.h>
#include <binder.hpp>
#include <gtk/os_utilities.hpp>

namespace view {
	void set_state( GtkWidget* w, adobe::eve_t::iterator i, adobe::eve_t* eve, bool visible ) {
		eve->set_visible( i, visible );
		eve->evaluate( adobe::eve_t::evaluate_nested );
		if( visible ) gtk_widget_show( w );
		else gtk_widget_hide( w );
	}
	void update_value( GtkWidget* w, adobe::eve_t::iterator i, adobe::eve_t& eve, const adobe::value_t& val ) {
		bool visible( false );
		if( !val.get( visible ) ) return;
		toolkit::application::getInstance().executeInMain(
			boost::bind( &set_state, w, i, &eve, visible )
		);
	}
	adobe::widget_node_t optional_factory( const adobe::dictionary_t& params, const adobe::widget_node_t& parent, const adobe::factory_token_t& token ) {
		//
		// Extract the thing to bind to first.
		//
		adobe::value_t binder = params.at( adobe::static_name_t( "bind" ) );
		//
		// We need to mark ourselves as a container.
		//
		adobe::eve_t::calculate_data_t cdata;
		cdata.placement_m = adobe::eve_t::place_column;
		//
		// We also need a fixed container to put children into so that
		// we can control visibility.
		//
		GtkWidget* container = gtk_fixed_new();
		token.assemblage_m.delete_on_destruction( container );
		adobe::display_t::position_t display_token( adobe::insert(
			adobe::get_main_display(), parent.display_token_m,
			container ) );
		adobe::display_t::position_t overlay_token(
			token.overlay_m.insert( parent.overlay_token_m ) );
		//
		// Bind the container into Eve.
		//
		adobe::eve_t::signal_suite_t signals;
		eve_client::place_func_t placer = boost::bind( &adobe::implementation::set_bounds_widget, container, _1, _2 );
		signals.eve_place_proc_m = boost::bind( &eve_client::utility_widget_place, placer, _1, _2, boost::ref( token.overlay_m ), overlay_token );
		//
		// Insert ourselves into the layout engine as
		// a non-create view.
		//
		adobe::eve_t::iterator i(
			token.layout_m.add_view_element( parent.eve_token_m,
				adobe::eve_t::insert_element_t(
					cdata,
					true,
					params,
					signals
					)
				)
			);
		//
		// Set it to be non-visible to start with.
		//
		token.layout_m.set_visible( i, false );
		//
		// Setup binder_helper_t from parameters, add to assemblage, connect, return.
		//
		adobe::binder_helper_t* bh = new adobe::binder_helper_t( token.sheet_m );
		token.assemblage_m.delete_on_destruction( bh );
		bh->initialize( binder, boost::bind( &update_value, container, i, boost::ref( token.layout_m ), _1 ), 0 );
		//
		// Return the new widget_node.
		//
		return adobe::widget_node_t( parent.size_m, i, display_token, overlay_token );
	}
}

